/**
 * Copyright (c) 2010-2011 julewa.com.  
 * All rights reserved. 
 * 
 * @author Huang Benhua
 * @date 2011-7-2
 * 
**/
package com.julewa.loading;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;

import com.julewa.Configuration;
import com.julewa.LOG;

public class SpringLoggerProcessor implements BeanPostProcessor {
	private @Autowired Configuration conf;
	private Set<String> forbiddenPkgs = new HashSet<String>();
	private class LoggerField{
		private Field field = null;
		private LOG logger = null;
		public LoggerField(Class<?> clazz){
			field = this.findField(clazz);
			if(field == null)return;
			field.setAccessible(true);
			Class<?> c = field.getDeclaringClass();
			if(Modifier.isStatic(field.getModifiers())){
				try {
					logger = (LOG)field.get(null);
					if(logger == null){
						logger = new LOG(c);
						field.set(null, logger);
					}
				} catch (Exception e) {
					e.printStackTrace();
				};
				field = null;
				return;
			}
			logger = new LOG(c);
		}
		private Field findField(Class<?> clazz){
			String pn = clazz.getPackage().getName();
			for(String p:forbiddenPkgs){
				if(pn.startsWith(p))return null;
			}
			Field fs[] = clazz.getDeclaredFields();
			for(Field f:fs){
				if(f.getType().equals(LOG.class)){
					return f;
				}
			}
			Class<?> c =  clazz.getSuperclass();
			if(c == null || c.equals(Object.class))return null;
			return findField(c);
		}
		public void process(Object obj){
			if(field == null)return;
			try {
				field.set(obj, logger);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	//
	@SuppressWarnings("unused")
	@PostConstruct
	private void init(){
		String ps[] = conf.getProperty("system.logger.ignore", "").split(",");
		for(String p:ps){
			if(p == null)continue;
			p = p.trim();
			if("".equals(p))continue;
			if(!p.endsWith(".")){
				p += ".";
			}
			forbiddenPkgs.add(p);
		}
		forbiddenPkgs.add("org.springframework.");
		forbiddenPkgs.add("com.opensymphony.");
		forbiddenPkgs.add("org.apache.");
		forbiddenPkgs.add("freemarker.");
		forbiddenPkgs.add("com.ibatis.");
	}
	//
	private Map<Class<?>, LoggerField> loggerFileds = new HashMap<Class<?>, LoggerField>();
	private LoggerField GetLoggerField(Class<?> clazz){
		LoggerField f = loggerFileds.get(clazz);
		if(f == null){
			f = new LoggerField(clazz);
			loggerFileds.put(clazz, f);
		}
		return f;
	}
	
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException { 
		return bean;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		GetLoggerField(bean.getClass()).process(bean);
		return bean;
	}
	
}
